Containers

  • Most containers live in System.Collections.Generic , as it:

    • avoids boxing

    • provides compile-time type safety

    • improves performance

    • avoids runtime casting

Array<T>

  • They are builtin into the language; the underlying type is defined on System.Array .

  • Fixed size

  • Contiguous memory

  • Reference type

int[] arr = new int[4];
arr[0] = 10;

Span<T>

  • From System .

  • A stack-only view over contiguous memory.

  • It allows safe access to:

    • arrays

    • stack memory

    • unmanaged buffers

  • Benefits:

    • avoids allocations

    • bounds checked

    • high performance

Span<int> s = stackalloc int[4];

s[0] = 10;
int[] arr = {1,2,3,4};

Span<int> s = arr;

Memory<T>

  • From System .

  • Heap-safe version of Span .

Memory<int> mem = new int[10];
  • Used in async contexts.

List<T>  ("dynamic Array<T> ")

  • Defined in the System.Collections.Generic  namespace.

  • wraps an array

  • dynamic size

  • may reallocate

  • Equivalent conceptually to std::vector  in C++.

List<int> list = new List<int>();

list.Add(1);
list.Add(2);

int v = list[0];

Dictionary<TKey, TValue>

  • Defined in the System.Collections.Generic  namespace.

  • Hash map.

Dictionary<int,string> map = new Dictionary<int,string>();
map[1] = "hello";

HashSet<T>

  • Defined in the System.Collections.Generic  namespace.

  • Hash set.

LinkedList<T>

  • Defined in the System.Collections.Generic  namespace.

  • Doubly linked list

Stack<T>

  • Defined in the System.Collections  namespace.

  • A stack follows the LIFO principle.

Stack<int> stack = new Stack<int>();

stack.Push(1);
stack.Push(2);

int v = stack.Pop();

Queue<T>

  • Defined in the System.Collections  namespace.

  • A queue follows the FIFO principle.

Queue<int> q = new Queue<int>();

q.Enqueue(1);
q.Enqueue(2);

int v = q.Dequeue();